import { Injectable } from '@nestjs/common';
import { and, eq, inArray, sql } from 'drizzle-orm';
import { DrizzleService } from '../../db/drizzle.service';
import { permissions, rolePermissions } from '../../db/schema';
import {
  CreatePermissionDto,
  UpdatePermissionDto,
  RolePermAuthDto
} from './dto/permission.schema';
import { BusinessException } from '../../common/exceptions/biz.exception';

@Injectable()
export class PermissionService {
  constructor(private readonly drizzle: DrizzleService) { }

  /**
   * 创建权限
   */
  async create(createPermDto: CreatePermissionDto) {
    // 检查权限标识是否已存在
    const existPerm = await this.drizzle.db
      .select({ count: sql<number>`count(*)` })
      .from(permissions)
      .where(eq(permissions.permissionKey, createPermDto.permissionKey));

    if (existPerm[0].count > 0) {
      throw new BusinessException('权限标识已存在');
    }

    return await this.drizzle.db.insert(permissions).values(createPermDto);
  }

  /**
   * 查询所有权限
   */
  async findAll() {
    return await this.drizzle.db.select().from(permissions);
  }

  /**
   * 查询单个权限
   */
  async findOne(id: number) {
    const permInfo = await this.drizzle.db
      .select()
      .from(permissions)
      .where(eq(permissions.permissionId, id));

    if (!permInfo || permInfo.length === 0) {
      throw new BusinessException('权限不存在');
    }

    return permInfo[0];
  }

  /**
   * 更新权限
   */
  async update(id: number, updatePermDto: UpdatePermissionDto) {
    const permInfo = await this.drizzle.db
      .select()
      .from(permissions)
      .where(eq(permissions.permissionId, id));

    if (!permInfo || permInfo.length === 0) {
      throw new BusinessException('权限不存在');
    }

    // 如果更新权限标识，需要检查是否已存在
    if (updatePermDto.permissionKey && updatePermDto.permissionKey !== permInfo[0].permissionKey) {
      const existPerm = await this.drizzle.db
        .select({ count: sql<number>`count(*)` })
        .from(permissions)
        .where(eq(permissions.permissionKey, updatePermDto.permissionKey));

      if (existPerm[0].count > 0) {
        throw new BusinessException('权限标识已存在');
      }
    }

    return await this.drizzle.db
      .update(permissions)
      .set(updatePermDto)
      .where(eq(permissions.permissionId, id));
  }

  /**
   * 删除权限
   */
  async remove(id: number) {
    // 判断是否有角色关联该权限
    const rolePermCount = await this.drizzle.db
      .select({ count: sql<number>`count(*)` })
      .from(rolePermissions)
      .where(eq(rolePermissions.permissionId, id));

    if (rolePermCount[0].count > 0) {
      throw new BusinessException('该权限存在关联角色，请先删除关联角色');
    }

    return await this.drizzle.db
      .delete(permissions)
      .where(eq(permissions.permissionId, id));
  }

  /**
   * 角色授权权限
   */
  async authorizeToRole(authDto: RolePermAuthDto) {
    const { roleId, permissionIds } = authDto;

    return await this.drizzle.db.transaction(async (tx) => {
      // 先删除原有关联
      await tx.delete(rolePermissions)
        .where(eq(rolePermissions.roleId, roleId));

      // 再添加新关联
      if (permissionIds.length > 0) {
        const values = permissionIds.map(permId => ({
          roleId,
          permissionId: permId
        }));
        await tx.insert(rolePermissions).values(values);
      }

      return { success: true, message: '授权成功' };
    });
  }

  /**
   * 查询角色的权限
   */
  async getPermissionsByRoleId(roleId: number) {
    const rolePerms = await this.drizzle.db
      .select({
        permissionId: rolePermissions.permissionId
      })
      .from(rolePermissions)
      .where(eq(rolePermissions.roleId, roleId));
    
    console.log('rolePerms', rolePerms);

    const permissionIds = rolePerms.map(rp => rp.permissionId);

    if (permissionIds.length === 0) {
      return [];
    }

    return await this.drizzle.db
      .select()
      .from(permissions)
      .where(inArray(permissions.permissionId, permissionIds));
  }

  /**
   * 查询多个角色的所有权限
   */
  async getPermissionsByRoleIds(roleIds: number[]) {
    if (roleIds.length === 0) {
      return [];
    }

    const rolePerms = await this.drizzle.db
      .select({
        permissionId: rolePermissions.permissionId
      })
      .from(rolePermissions)
      .where(inArray(rolePermissions.roleId, roleIds));

    const permissionIds = rolePerms.map(rp => rp.permissionId);

    if (permissionIds.length === 0) {
      return [];
    }

    return await this.drizzle.db
      .select()
      .from(permissions)
      .where(inArray(permissions.permissionId, permissionIds));
  }
} 